// Copyright 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "proto_compiler.h"

#include <iostream>
#include <sstream>
#include <string>
#include "google/protobuf/compiler/importer.h"

using google::protobuf::compiler::DiskSourceTree;
using google::protobuf::compiler::MultiFileErrorCollector;
using google::protobuf::compiler::Importer;
using google::protobuf::FileDescriptor;
using google::protobuf::FileDescriptorProto;
using std::cerr;
using std::endl;
using std::ostringstream;

namespace {

class StdErrErrorCollector : public MultiFileErrorCollector {
 public:
  virtual void AddError(const std::string& filename, int line, int column,
                        const std::string& message) {
    cerr << filename << ":" << line << ":" << column << ": " << message
         << endl;
  }
};

// Implementation of the ProtoCompiler interface.
class ProtoCompilerImpl : public ProtoCompiler {
 public:
  ProtoCompilerImpl() : importer_(&source_tree_, &error_collector_) {}

  virtual void map_path(const std::string &virtual_path,
                        const std::string &disk_path) {
    source_tree_.MapPath(virtual_path, disk_path);
  }

  virtual std::string parse(const std::string &filename) {
    const FileDescriptor* file_des = importer_.Import(filename);
    if (!file_des)
      return "";

    // Convert to a string proto.
    FileDescriptorProto proto;
    file_des->CopyTo(&proto);
    ostringstream out;
    proto.SerializeToOstream(&out);
    return out.str();
  }

 private:
  DiskSourceTree source_tree_;
  StdErrErrorCollector error_collector_;
  Importer importer_;
};

}

ProtoCompiler::~ProtoCompiler() {}

ProtoCompiler* ProtoCompiler::create() {
    return new ProtoCompilerImpl();
}
